package com.xbk.seckill.ratelimiter.concurrent.bean;

import com.xbk.seckill.common.exception.ErrorCode;
import com.xbk.seckill.common.exception.SeckillException;

import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author xiexu
 * @date 2025/05/07 14:38
 */
public class BHConcurrentRateLimiter {

    /**
     * 线程池对象
     */
    private ThreadPoolExecutor executor;

    /**
     * 超时时间
     */
    private long timeout;

    /**
     * 超时时间单位
     */
    private TimeUnit timeoutUnit;

    public BHConcurrentRateLimiter() {
    }

    public BHConcurrentRateLimiter(ThreadPoolExecutor executor, long timeout, TimeUnit timeoutUnit) {
        this.executor = executor;
        this.timeout = timeout;
        this.timeoutUnit = timeoutUnit;
    }

    public ThreadPoolExecutor getExecutor() {
        return executor;
    }

    public void setExecutor(ThreadPoolExecutor executor) {
        this.executor = executor;
    }

    public long getTimeout() {
        return timeout;
    }

    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    public TimeUnit getTimeoutUnit() {
        return timeoutUnit;
    }

    public void setTimeoutUnit(TimeUnit timeoutUnit) {
        this.timeoutUnit = timeoutUnit;
    }

    public void execute(Runnable command) {
        executor.execute(command);
    }

    /**
     * 向线程池中提交任务
     *
     * @param task
     * @param <T>
     * @return
     */
    public <T> T submit(Callable<T> task) {
        try {
            return executor.submit(task).get();
        } catch (Exception e) {
            if (e instanceof SeckillException) {
                throw (SeckillException) e;
            }
            throw new SeckillException(ErrorCode.SERVER_EXCEPTION);
        }
    }

    /**
     * 提交异步任务到线程池，并在指定时间内等待结果，超时或异常时抛出指定异常
     *
     * @param task
     * @param <T>
     * @return
     */
    public <T> T submitWithTimeout(Callable<T> task) {
        try {
            return executor.submit(task).get(timeout, timeoutUnit);
        } catch (Exception e) {
            if (e instanceof SeckillException) {
                throw (SeckillException) e;
            }
            throw new SeckillException(ErrorCode.SERVER_EXCEPTION);
        }
    }

    /**
     * 关闭线程池
     */
    public void shutdown() {
        if (executor != null) {
            executor.shutdown();
        }
    }
}
